//
//  Interlock_arm_ios.h
//  TestLib
//
//  Created by Oray on 12-2-16.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef TestLib_Interlock_arm_ios_h
#define TestLib_Interlock_arm_ios_h

#include <libkern/OSAtomic.h>

static OSSpinLock g_osx_lock = OS_SPINLOCK_INIT;
static int long_size = sizeof(long);

/*++
 Function:
 InterlockedIncrement
 
 The InterlockedIncrement function increments (increases by one) the
 value of the specified variable and checks the resulting value. The
 function prevents more than one thread from using the same variable
 simultaneously.
 
 Parameters
 
 lpAddend 
 [in/out] Pointer to the variable to increment. 
 
 Return Values
 
 The return value is the resulting incremented value. 
 
 --*/
inline long
InterlockedIncrement(
                     long volatile *lpAddend)
{
    if (long_size == 4)
        return OSAtomicAdd32((int32_t)1, (int32_t volatile *)lpAddend);
    else
        return OSAtomicAdd64((int64_t)1, (int64_t volatile*)lpAddend);
}


/*++
 Function:
 InterlockedDecrement
 
 The InterlockedDecrement function decrements (decreases by one) the
 value of the specified variable and checks the resulting value. The
 function prevents more than one thread from using the same variable
 simultaneously.
 
 Parameters
 
 lpAddend 
 [in/out] Pointer to the variable to decrement. 
 
 Return Values
 
 The return value is the resulting decremented value.
 
 --*/
inline
long
InterlockedDecrement(
                     long volatile *lpAddend)
{
    if (long_size == 4)
        return OSAtomicAdd32((int32_t)-1, (int32_t volatile *)lpAddend);	//return var;
    else
        return OSAtomicAdd64((int64_t)-1, (int64_t volatile *)lpAddend);	//return var;
}


/*++
 Function:
 InterlockedExchange
 
 The InterlockedExchange function atomically exchanges a pair of
 values. The function prevents more than one thread from using the same
 variable simultaneously.
 
 Parameters
 
 Target 
 [in/out] Pointer to the value to exchange. The function sets
 this variable to Value, and returns its prior value.
 Value 
 [in] Specifies a new value for the variable pointed to by Target. 
 
 Return Values
 
 The function returns the initial value pointed to by Target. 
 
 --*/

inline long
InterlockedExchange(volatile long* target, long new_value) {
    long old_value;
    if (long_size == 4)
    {
        do {
            old_value = *target;
        } while (!OSAtomicCompareAndSwap32(old_value, new_value,
                                           reinterpret_cast<volatile int32_t*>(target)));
    }
    else
    {
        do {
            old_value = *target;
        } while (!OSAtomicCompareAndSwap64(old_value, new_value,
                                           reinterpret_cast<volatile int64_t*>(target)));
    }
    return old_value;
}


/*++
 Function:
 InterlockedCompareExchange
 
 The InterlockedCompareExchange function performs an atomic comparison
 of the specified values and exchanges the values, based on the outcome
 of the comparison. The function prevents more than one thread from
 using the same variable simultaneously.
 
 If you are exchanging pointer values, this function has been
 superseded by the InterlockedCompareExchangePointer function.
 
 Parameters
 
 Destination     [in/out] Specifies the address of the destination value. The sign is ignored. 
 Exchange        [in]     Specifies the exchange value. The sign is ignored. 
 Comperand       [in]     Specifies the value to compare to Destination. The sign is ignored. 
 
 Return Values
 
 The return value is the initial value of the destination.
 
 --*/
//if( InterlockedCompareExchange(&m_lConnected,1,0) == 0)
inline long
InterlockedCompareExchange(
                           long volatile *Destination,
                           long Exchange,
                           long Comperand)
{
    OSSpinLockLock(&g_osx_lock);
    long val = *Destination;
    if (Comperand == val)
    {
        val = InterlockedExchange(Destination, Exchange);
    }
    
    OSSpinLockUnlock(&g_osx_lock);
    return val;
    
//    bool    OSAtomicCompareAndSwap32( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue );

    /*! @abstract Compare and swap for 32-bit values.
     @discussion
     This function compares the value in <code>__oldValue</code> to the value
     in the memory location referenced by <code>__theValue</code>.  If the values
     match, this function stores the value from <code>__newValue</code> into
     that memory location atomically.
     @result Returns TRUE on a match, FALSE otherwise.
    return old_value;
     */
}


#endif
